home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 January / EnigmA AMIGA RUN 33 (1999)(G.R. Edizioni)(IT)[!][issue 1999-01].iso / earcd / apus / boothack / old / bh980726.lha / bh980726-2 / ppc_boot.c < prev    next >
C/C++ Source or Header  |  1997-02-22  |  7KB  |  364 lines

  1. /****************************************************************************
  2.  * ppc_boot.c -- This program initializes the PPC on a Phase5 PowerUp board
  3.  *               and boots the kernel.
  4.  *
  5.  * Copyright 1997, 1998 by Jesper Skov (jskov@cygnus.co.uk)
  6.  ***************************************************************************/
  7.  
  8. #define SYMBOL_NAME_STR(X) #X
  9.  
  10. #define INTENA 0xdff09a
  11. #define INTREQ 0xdff09c
  12.  
  13. #define CHIP_PTR (0xfff00)
  14.  
  15. #define REG_SHADOW (0xf60018)
  16. #define REGSHADOW_SETRESET (0x80)
  17. #define REGSHADOW_SHADOW   (0x01)
  18.  
  19. #include <exec/types.h>
  20. #include <exec/nodes.h>
  21. #include <exec/lists.h>
  22. #include <exec/memory.h>
  23. #include <powerup/ppclib/interface.h>
  24. #include <powerup/gcclib/powerup_protos.h>
  25.  
  26. void goSupervisor(void);
  27. void relocate(void);
  28. extern char relocateEnd;
  29.  
  30. void progress_init (void);
  31. void progress (char);
  32.  
  33. unsigned int main(void)
  34. {
  35.     int i;
  36.     unsigned long *s, *d;
  37.     unsigned long ptr;
  38.  
  39.     register unsigned long r0 __asm("r0");
  40.     register unsigned long r3 __asm("r3");
  41.  
  42.     progress_init ();
  43.     progress ('a');
  44.     
  45.     {
  46.         /* Wait for the m68k to complete its business (shutting up
  47.          * boards).
  48.          * It would be better to do proper synchronization, but my
  49.          * attempts to do something "nice" failed. I think it's
  50.          * because the m68k drops everything on the floor when it
  51.          * attempts to write the same address the PPC is polling.
  52.          * The PPC uKernel could be used to send a signal, but then
  53.          * there's no way to be sure "where" the m68k is when the
  54.          * PPC disables interrupts. Therefore this loop for now.
  55.          */
  56.         int fingers_crossed = 1;
  57.         for (i = 0; i < 1000000;i++);
  58.  
  59.     }
  60.  
  61.     progress ('b');
  62.  
  63.     {
  64.         unsigned short* intena_p = (unsigned short*) INTENA;
  65.         unsigned short* intreq_p = (unsigned short*) INTREQ;
  66.         /* Disable IRQs. */
  67.         *intena_p = 0x7fff;
  68.         *intreq_p = 0x7fff;
  69.     }
  70.  
  71.     progress ('c');
  72.  
  73.     /* Get the PR bit set. */
  74.     goSupervisor();
  75.  
  76.     progress ('d');
  77.     
  78.     PPCCacheFlushAll();
  79.     __asm __volatile (
  80.         /* Disable caches. */
  81.         "mfspr 0,1008       \n\t" /* HID0 */
  82.         "lis   3,0          \n\t"
  83.         "ori   3,3,0xc000   \n\t" /* HID0_ICE|HID0_DCE */
  84.         "andc  0,0,3        \n\t"
  85.         "sync               \n\t"
  86.         "isync              \n\t"
  87.         "mtspr 1008,0       \n\t" /* HID0 */
  88.         /* Disable address translation. */
  89.         "mfmsr 0            \n\t"
  90.         "li    3,0b110000   \n\t" /* MSR_IR|MSR_DR */
  91.         "andc  0,0,3        \n\t"
  92.         "isync              \n\t"
  93.         "mtmsr 0            \n\t"
  94.         "sync               \n\t"
  95.         :: "r" (r0), "r" (r3));
  96.  
  97.  
  98.         /* I don't know if this works so it is disabled until someone with a
  99.            blizzard verifies the effect. mm/init.c will need to be adjusted
  100.            if this code is activated (init makes presumptions about
  101.            shadowing based on memory size). */ 
  102. #if 0 
  103.     { 
  104.         unsigned char* reg_shadow =    (unsigned char*) REG_SHADOW; 
  105.         *reg_shadow = (REGSHADOW_SETRESET |    REGSHADOW_SHADOW);
  106.     } 
  107. #endif 
  108.  
  109.     progress ('e');
  110.  
  111.     /* Get info-ptr from CHIP_PTR. 
  112.      * Relocate code to memory just above info. 
  113.      */
  114.     ptr = (unsigned long) *((unsigned long*) CHIP_PTR);
  115.     ptr += 0x0200;
  116.     ptr = ptr + 4 - (ptr % 4);
  117.  
  118.     s = (unsigned long*) &relocate;
  119.     d = (unsigned long*) ptr;
  120.     for(i = (((unsigned long)&relocateEnd) - ((unsigned long)s))/4;
  121.         i >= 0; i--){
  122.         *d = *s;
  123.         d++;
  124.         s++;
  125.     }
  126.  
  127.     progress ('f');
  128.     
  129.     /* Jump to relocated code. */
  130.     r0 = ptr;
  131.     __asm __volatile (
  132.         "mtlr  0             \n\t"
  133.         "blr    \n\t"
  134.         : /* no outputs */
  135.         : "r" (r0), "r" (r3)
  136.         /* no return */);
  137.     
  138.     /* fake a noreturn */
  139.     for (;;);
  140.         
  141.     return;
  142. }
  143.  
  144. void relocate(void)
  145. {
  146.     const unsigned long *info;
  147.     unsigned char *s, *d, *e;
  148.  
  149.     progress ('g');
  150.  
  151.     /* Get info-ptr from CHIP_PTR. */
  152.     info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
  153.  
  154.     /* Verify checksum. */
  155.     if (info[7])
  156.     {
  157.         int i = (info[2] + info[3]) / 4;
  158.         unsigned char* k_p = (unsigned char*) info[0];
  159.         unsigned long kcs = 0;
  160.         
  161.         while (i--)
  162.         {
  163.             unsigned long w = 0;
  164.                 
  165.             w |= *k_p++;
  166.             w <<= 8;
  167.             w |= *k_p++;
  168.             w <<= 8;
  169.             w |= *k_p++;
  170.             w <<= 8;
  171.             w |= *k_p++;
  172.  
  173.                 
  174.             kcs = kcs ^ i;
  175.             kcs = kcs ^ w;
  176.         }
  177.         progress ('C');
  178.         progress ('1');
  179.         if (info[7] == kcs)
  180.             progress ('+');
  181.         else
  182.             progress ('-');
  183.     }
  184.  
  185.     /* Copy kernel to memstart */
  186.     s = (unsigned char *) info[0];
  187.     d = (unsigned char *) info[1];
  188.     e = (unsigned char *) (info[1] + info[2] + info[3]);
  189.     while(d != e){
  190.         *d = *s;
  191.         s++;
  192.         d++;
  193.     }
  194.  
  195.     progress ('h');
  196.  
  197.     /* Verify checksum. */
  198.     if (info[7])
  199.     {
  200.         int i = (info[2] + info[3]) / 4;
  201.         unsigned char* k_p = (unsigned char*) info[1];
  202.         unsigned long kcs = 0;
  203.         
  204.         while (i--)
  205.         {
  206.             unsigned long w = 0;
  207.                 
  208.             w |= *k_p++;
  209.             w <<= 8;
  210.             w |= *k_p++;
  211.             w <<= 8;
  212.             w |= *k_p++;
  213.             w <<= 8;
  214.             w |= *k_p++;
  215.  
  216.                 
  217.             kcs = kcs ^ i;
  218.             kcs = kcs ^ w;
  219.         }
  220.         progress ('C');
  221.         progress ('2');
  222.         if (info[7] == kcs)
  223.             progress ('+');
  224.         else
  225.             progress ('-');
  226.     }
  227.     
  228.     /* Copy ramdisk to memory end. */
  229.     d = (unsigned char *) info[1] + info[5];
  230.     e = d - info[4];
  231.     s = s + info[4];
  232.     while(d != e){
  233.         s--;
  234.         d--;
  235.         *d = *s;
  236.     }
  237.  
  238.     progress ('i');
  239.  
  240.     /* Let 0xfff00000 contain sum used for VTOP/PTOV in head.S. */
  241.     /* Also put it at kernel start since kernel copies the vectors
  242.      * to their proper location after modifying a few instructions.
  243.      */
  244. #define KERNELBASE 0xC0000000
  245.     *((unsigned long *)0xfff00000) = info[1] - KERNELBASE;
  246.     *((unsigned long *) info[1]) = info[1] - KERNELBASE;
  247.  
  248.     progress ('K');
  249.  
  250.     {
  251.         register unsigned long r3 __asm("r3");
  252.         register unsigned long r4 __asm("r4");
  253.         register unsigned long r5 __asm("r5");
  254.         register unsigned long r6 __asm("r6");
  255.         register unsigned long r7 __asm("r7");
  256.  
  257.         /* initrd pointers (virtual addresses) */
  258.         if (info[4]){
  259.             /* end of rd */
  260.             r5 = info[5] + KERNELBASE;
  261.             /* start of rd */
  262.             r4 = r5 - info[4];
  263.         } else
  264.             r4 = 0;
  265.         
  266.         /* Make it easy to identify APUS in identify_machine. */
  267.         r3 = 0x61707573;
  268.         
  269.         /* Jump to kernel start. */
  270.         r7 = info[1] + 0xc;
  271.         __asm __volatile (
  272.             "mtlr 7 \n\t"
  273.             "blr    \n\t"
  274.             : /* no outputs */
  275.             : "r" (r3), "r" (r4), "r" (r5), "r" (r6), "r" (r7)
  276.             /* no return */);
  277.     }
  278.     
  279.     /* fake a noreturn */
  280.     for (;;);
  281. }
  282.  
  283. /* Play that jive... */
  284. extern char setPR, setPRend;
  285. void goSupervisor(void)
  286. {
  287.     unsigned long *s, *d;
  288.     int len = ((int) &setPRend - (int) &setPR) / 4;
  289.  
  290.     /* Copy code to TRAP entry */
  291.     d = (unsigned long*) 0xfff00700;
  292.     s = (unsigned long*) &setPR;
  293.     for(;len > 0;len--){
  294.         *d = *s;
  295.         d++;
  296.         s++;
  297.     }
  298.  
  299.     PPCCacheFlushAll();
  300.     
  301.     /* Execute code */
  302.     __asm__ (
  303.         "trap \n\t"
  304.         );
  305. }
  306.  
  307. void progress_init (void)
  308. {
  309.     const unsigned long *info;
  310.     unsigned long *mesg_base;
  311.     unsigned long* p;
  312.     info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
  313.     mesg_base = (unsigned long*) info[6];
  314.     p = mesg_base;
  315.     
  316.     *p++ = 'SAVE';
  317.     *p++ = 'BOOT';
  318.     *p++ = (unsigned long) mesg_base;
  319.     *p++ = 0;
  320. }
  321.     
  322.  
  323. void progress (char c)
  324. {
  325.     const unsigned long *info;
  326.     char progress_state;
  327.     char* progress_ptr;
  328.     unsigned long* mesg_base;
  329.     info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
  330.  
  331.     mesg_base = (unsigned long*) info[6];
  332.  
  333.     progress_ptr = mesg_base[3] + (char*)&mesg_base[4];
  334.     *progress_ptr = c;
  335.     mesg_base[3]++;
  336. }
  337.  
  338. asm(
  339.     ".text\n"
  340.     ".align 4\n"
  341.     SYMBOL_NAME_STR(setPR) ":
  342. /* Increase the return EA so we get to the next instruction */
  343. mtsprg       1,1
  344. mfsrr0       1
  345. addi         1,1,4
  346. mtsrr0       1
  347. mfsprg       1,1
  348. /* Fiddle the PR bit */
  349. mfsrr1       0
  350. rlwinm       0,0,0,18,16
  351. mtsrr1       0
  352. rfi
  353. "
  354.     SYMBOL_NAME_STR(setPRend) ":
  355. ");
  356.  
  357. asm(
  358.     ".text\n"
  359.     ".align 4\n"
  360.     SYMBOL_NAME_STR(relocateEnd) ":
  361. nop
  362. "
  363.     );
  364.